package com.base.cn.platform.os.service.order.check;

import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.order.ShopType;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.entity.op.coupon.OpCouponCode;
import com.base.cn.platform.os.entity.op.coupon.OpCouponShop;
import com.base.cn.platform.os.entity.order.shop.ShopData;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 优惠券验证对象
 *
 * @author s.li
 * @date 2019/05/27
 */
public class CouponCodeCheckObserver extends  OrderCheckObserver{

    public CouponCodeCheckObserver(CreateOrderDataFrom createOrderDataFrom) {
        this.createOrderDataFrom  = createOrderDataFrom;
        this.createOrderDataFrom.addObserver(this);
    }

    @Override
    public Map<String, Object> orderCheck() {
        Map<String,Object> errorResultMap = ResultUtil.ERROR();
        errorResultMap.put("errorType","CODE");
        OpCouponCode couponCode = createOrderDataFrom.getCouponCode();
        if(couponCode== null && !createOrderDataFrom.isQueryCouponCode()){
            couponCode = opCouponCodeBiz.findCouponCodeByCode(createOrderDataFrom.getCode(),false);
            createOrderDataFrom.setQueryCouponCode(true);
            //设置优惠券对象
            createOrderDataFrom.setCouponCode(couponCode);
        }
        if(couponCode==null){
            ResultUtil.setMessage(errorResultMap,"【"+createOrderDataFrom.getCode()+"】优惠券不存在");
            return errorResultMap;
        }
        List<ShopData> shopDataList = createOrderDataFrom.getShopList();
        Map<String,List<ShopData>> shopDataListMap = shopDataList.stream().collect(Collectors.groupingBy(e->e.getShopType()));
        List<ShopData> accountShopList = shopDataListMap.get(ShopType.ORDER_SHOP_ACCOUNT);
        if(ObjectUtils.isNotEmpty(accountShopList)){
            ResultUtil.setMessage(errorResultMap,"账户充值订单不可使用优惠券");
            return errorResultMap;
        }
        if(couponCode.getUserId().intValue() != 0 && couponCode.getUserId().compareTo(createOrderDataFrom.getUserId()) !=0){
            ResultUtil.setMessage(errorResultMap,"该优惠券不属于当前登录用户");
            return errorResultMap;
        }
        if(couponCode.getStatus() !=1){
            ResultUtil.setMessage(errorResultMap,"优惠券不可用");
            return errorResultMap;
        }
        if(couponCode.getTimeType()==1){//1自定义时间段
            //当前时间
            Date nowTime = new Date();
            //开始时间
            Date beginTime = couponCode.getBeginTime();
            if(beginTime.after(nowTime)){
                ResultUtil.setMessage(errorResultMap,"优惠券未能使用");
                return errorResultMap;
            }
            //结束时间
            Date endTime = couponCode.getEndTime();
            if(endTime.before(nowTime)){
                ResultUtil.setMessage(errorResultMap,"优惠券已过期");
                return errorResultMap;
            }
        }

        double shopPrice;
        //可优惠的商品列表
        List<ShopData> rangeShopList = new ArrayList<>();
        if(couponCode.getSettingStatus()==1){//有使用条件限制
            //获取优惠券中的商品
            List<OpCouponShop> couponShopList = opCouponShopBiz.findCouponShopList(couponCode.getCouponId());

            //以商品类型分组
            Map<String,List<OpCouponShop>> stringListMap = couponShopList.stream().collect(Collectors.groupingBy(e->e.getShopType()));
            //以商品类型和ID转Map
            Map<String,OpCouponShop> couponShopMap = couponShopList.stream().collect(Collectors.toMap(e->e.getShopType()+e.getShopId(),e->e));
            //以商品类型和ID转Map
            Map<String,ShopData> shopMap = shopDataList.stream().collect(Collectors.toMap(e->e.getShopType()+e.getShopId(),e->e));
            //以商品类型分组
            Map<String,List<ShopData>> shopListMap = shopDataList.stream().collect(Collectors.groupingBy(e->e.getShopType()));
            couponShopMap.forEach((k,v)->{
                ShopData shop = shopMap.get(k);
                if(ObjectUtils.isNotEmpty(shop)){
                    rangeShopList.add(shop);
                }
            });
            //因为问答和旁听条件的ID都是0，因此问答和旁听单独处理
            //获取问答数据
            List<OpCouponShop> qaCouponShop = stringListMap.get(ShopType.ORDER_SHOP_QA);
            if(ObjectUtils.isNotEmpty(qaCouponShop)){
                List<ShopData> qaShopList = shopListMap.get(ShopType.ORDER_SHOP_QA);
                if(ObjectUtils.isNotEmpty(qaShopList)){
                    rangeShopList.addAll(qaShopList);
                }
            }
            //获取旁观数据
            List<OpCouponShop> attendCouponShop =stringListMap.get(ShopType.ORDER_SHOP_ATTEND);
            if(ObjectUtils.isNotEmpty(attendCouponShop)){
                List<ShopData> attendShopList = shopListMap.get(ShopType.ORDER_SHOP_ATTEND);
                if(ObjectUtils.isNotEmpty(attendShopList)){
                    rangeShopList.addAll(attendShopList);
                }
            }
            if(!ObjectUtils.isNotEmpty(rangeShopList)){
                ResultUtil.setMessage(errorResultMap,"支付商品不可使用优惠券");
                return errorResultMap;
            }
        }else if(couponCode.getSettingStatus()==2){//没有限制条件
            rangeShopList.addAll(shopDataList);
        }
        if(createOrderDataFrom.isMemberUser()){
            shopPrice = rangeShopList.stream().mapToDouble(e->e.getMemberPrice()).sum();
        }else{
            shopPrice = rangeShopList.stream().mapToDouble(e->e.getRealPrice()).sum();
        }
        if(couponCode.getMinAmount() > shopPrice){
            ResultUtil.setMessage(errorResultMap,"订单金额未达到优惠券最低限额【￥"+couponCode.getMinAmount()+"】");
            return errorResultMap;
        }

        //重新设置的价格
        this.setCouponCodeSubPrice(rangeShopList,couponCode.getType(),couponCode.getLimitAtion());

        return ResultUtil.SUCCESS();
    }

    /**
     * 设置优惠券减免金额
     * @param shopList 商品列表
     * @param type 优惠券类型 1折扣券 2定额
     * @param limitAtion 优惠限额，type=1时为折扣，type=2时为金额
     */
    private void setCouponCodeSubPrice(List<ShopData> shopList,int type,double limitAtion){
        if(type==1){//折扣
            shopList.forEach(shop->{
                double _subPrice;
                if("3".equals(createOrderDataFrom.getSelaSwitch())
                        && createOrderDataFrom.isMemberUser()) {//会员价格
                    double shopMemberPrice = shop.getMemberPrice();
                    double shopRealPrice = shop.getRealPrice();
                    //得到折扣的会员会员价格
                    double price = shopMemberPrice * (limitAtion / 10);
                    //得到减的金额
                    _subPrice = shopMemberPrice - price;
                    //得到会员减免金额
                    double memberSubPrice = shopRealPrice - shopMemberPrice;
                    shop.setMemberSubPrice(memberSubPrice);

                    //得到商品的最后的价格
                    shop.setRealPrice(price);
                    shop.setMemberPrice(price);
                }else{
                    double price = shop.getRealPrice() * (limitAtion / 10);
                    _subPrice = shop.getRealPrice()  - price;
                    shop.setRealPrice(price);
                }
                shop.setDiscountSubPrice(_subPrice);
            });
        }
        if(type==2){//立减
            this.setSubPrice(shopList,limitAtion);
        }
    }

    /**
     * 设置减免金额
     * @param shopList 商品列表
     * @param subPrice 减免的金额
     */
    private void setSubPrice(List<ShopData> shopList, double subPrice){
        //商品数据存在才可能使用优惠券
        if(ObjectUtils.isNotEmpty(shopList)){
            //商品总价格
            double shopSumPrice = shopList.stream().mapToDouble(e->e.getRealPrice()).sum();
            //会员总价格
            double shopMemberSumPrice = shopList.stream().mapToDouble(e->e.getMemberPrice()).sum();
            shopList.forEach(shop ->{
                double _subPrice;
                if(createOrderDataFrom.isMemberUser()
                        && "3".equals(createOrderDataFrom.getSelaSwitch())){//会员价格
                    //得到商品减免金额
                    _subPrice = subPrice * (shop.getMemberPrice() / shopMemberSumPrice);
                    double memberPrice = shop.getMemberPrice() - _subPrice;
                    shop.setRealPrice(memberPrice);
                    //算出会员优惠价格
                    shop.setMemberSubPrice(shop.getRealPrice() - shop.getMemberPrice());
                    shop.setMemberPrice(memberPrice);
                }else{//非会员价格
                    _subPrice = (shop.getRealPrice() / shopSumPrice) * subPrice;
                    shop.setRealPrice(shop.getRealPrice() - _subPrice);
                }
                //优惠券减免金额
                shop.setDiscountSubPrice(_subPrice);
            });
        }
    }
}
